package ofxdownloader;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import ofxdownloader.InputDateParser.InvalidDateFormatException;
import ofxdownloader.OFXConnector.OFXSignOnException;
import ofxdownloader.OFXResponseParser.OFXParseException;

/**
 * This class is the external interface to downloading account lists and 
 * account statements from an OFX server
 * @author Alex Spurling
 *
 */
public class NationwideOFXDownloader {
	
	/** Used to perform the connection to the OFX server */
	OFXConnector connector;
	
	public NationwideOFXDownloader() {
		connector = new OFXConnector();
	}
	
	/**
	 * Get an account list using the given signon details
	 * @param signOnInfo
	 * @return
	 * @throws OFXSignOnException
	 * @throws OFXParseException
	 */
	private List<Account> getAccountList(SignOnInfo signOnInfo) throws OFXSignOnException, OFXParseException {
		OFXRequest accountListRequest = new AccountListRequest(signOnInfo);
		
		OFXResponse response = connector.getOFXResponse(accountListRequest);
		
		return OFXResponseParser.getAccountList(response);
	}
	
	/**
	 * Get a statement for an account with the given details 
	 * @param account
	 * @param fromDate
	 * @param toDate
	 * @param signOnInfo
	 * @return
	 * @throws OFXSignOnException
	 */
	private OFXResponse getStatement(Account account, Date fromDate, Date toDate, SignOnInfo signOnInfo) throws OFXSignOnException {
		OFXRequest statementRequest = new StatementRequest(account, fromDate, toDate, signOnInfo);
		
		return connector.getOFXResponse(statementRequest);
	}
	
	/**
	 * Save an ofx response to a file
	 * @param response
	 * @param file
	 */
	private void saveOFX(OFXResponse response, File file) {
		try {
			BufferedWriter outputStream = new BufferedWriter(new FileWriter(file));
			
			outputStream.write(response.toString());
			outputStream.flush();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		
		if (args.length != 3 && args.length != 7) {
			System.out.println("The Nationwide OFX Downloader is able to connect to Nationwide Building");
			System.out.println("Society internet banking servers and download a list of available ");
			System.out.println("accounts or an OFX file containing statement information.");
			System.out.println("WARNING: only enter your actual internet bank details if you");
			System.out.println("checked and compiled the code yourself!");
			System.out.println("Triple check that you are entering your correct bank details; you may get");
			System.out.println("locked out of your account if you enter in the wrong details several times!");
			System.out.println("");
			System.out.println("Usage: NationwideOFXDownloader customernum memorabledata passnum [accountnum] [fromdate] [todate] [outputfile]");
			System.out.println("If the account number, date and output file parameters are ommited then a list");
			System.out.println("of your available internet banking accounts are displayed.");
			System.out.println("The date parameters can be entered as specific dates, or as relative dates.");
			System.out.println("Specifying 'start' for the fromdate or 'end' for the todate will retreive data");
			System.out.println("from the earliest available start date or the latest available end date");
			System.out.println("");
			System.out.println("Examples:");
			System.out.println("gets a statement for a 1 month period:");
			System.out.println("NationwideOFXDownloader 0123456789 mypetsname 123456 0456/6123456 09May08 09Jun08 JuneStatement.ofx");
			System.out.println("gets a statement for the most recent 30 days:");
			System.out.println("NationwideOFXDownloader 0123456789 mypetsname 123456 0456/6123456 30days end LatestStatement.ofx");
			System.out.println("gets a statement for a 3 month period after a given date");
			System.out.println("NationwideOFXDownloader 0123456789 mypetsname 123456 0456/6123456 23Feb06 3months LatestStatement.ofx");
			return;
		}
		
		String customerID = args[0];
		String memorableData = args[1];
		String passNumber = args[2];

		String accountNum = "";
		String fromDateStr = "";
		String toDateStr = "";
		String outputFile = "";
		Date fromDate = null;
		Date toDate = null;

		if (args.length == 7) {
			accountNum = args[3];
			fromDateStr = args[4];
			toDateStr = args[5];
			outputFile = args[6];
			
			try {
				fromDate = InputDateParser.getFromDate(fromDateStr, toDateStr);
				toDate = InputDateParser.getToDate(fromDateStr, toDateStr);
			} catch (InvalidDateFormatException e1) {
				System.out.println(e1.getMessage());
				return;
			}
		}
		
		SignOnInfo signOnInfo = new SignOnInfo(customerID, memorableData, passNumber);

		NationwideOFXDownloader downloader = new NationwideOFXDownloader();

		try {
			System.out.println("Getting account list...");
			List<Account> accountList = downloader.getAccountList(signOnInfo);
			
			if (accountList == null || accountList.size() == 0) {
				System.out.println("Error: No accounts found.");
				return;
			}
			
			if (args.length == 3) {
				//Just display account list and quit
				for (int i = 0; i < accountList.size(); i++) {
					Account account = accountList.get(i);
					System.out.println("Account #1: " + account.getDescription() + ", Num: " + account.getAccountID() + ", Type: " + account.getAccountType());
				}
				return;
			}else if (args.length == 7) {
	
				Account theAccount = null;
				//Try to find the given account
				for (Account account: accountList) {
					if (accountNum.equals(account.getAccountID())) {
						System.out.println("Account " + accountNum + " found. Getting statement...");
						theAccount = account;
					}
				}
				if (theAccount == null) {
					System.out.println("The account: " + accountNum + " could not be found. ");
					return;
				}
				
				//Download the OFX file!
				OFXResponse statement = downloader.getStatement(theAccount, fromDate, toDate, signOnInfo);
				
				downloader.saveOFX(statement, new File(outputFile));
				
				System.out.println("Statement downloaded to " + outputFile);
			}
		
		} catch (OFXSignOnException e) {
			System.err.println("Error signing on. Triple check your sign on details before trying again or your account may be locked out!");
			System.err.println(e.getMessage());
		} catch (OFXParseException e) {
			System.err.println("Error getting account list");
			e.printStackTrace();
		}
	}

	
	
	

}
